<template>
    <div>
        <el-button type="text" @click="$refs['fileInput'].click()">点击上传</el-button>
        <input type="file" multiple style="display: none" ref="fileInput" @change="selectedFile">
        <span class="el-upload__tip text-gray">支持任何文件格式，不超过10MB。{{placeholder}}</span>
        <el-table :data="files" border stripe>
            <el-table-column label="文件名">
                <template slot-scope="scope">
                    <template v-if="[2,4].indexOf(scope.row.status) === -1">{{scope.row.file.name}}</template>
                    <el-tag v-else @click.native="clickFile(scope.row)" class="cursor-pointer">{{scope.row.file.name}}
                    </el-tag>
                </template>
            </el-table-column>
            <el-table-column label="上传状态">
                <template slot-scope="scope">
                    <template v-if="0 === scope.row.status">等待上传</template>
                    <template v-else-if="1 === scope.row.status">上传中</template>
                    <template v-else-if="2 === scope.row.status">上传成功</template>
                    <template v-else-if="3 === scope.row.status">
                        上传失败<br>
                        <el-tag type="error">{{scope.row.error}}</el-tag>
                    </template>
                    <template v-else-if="4 === scope.row.status">以前上传</template>
                </template>
            </el-table-column>
            <el-table-column label="操作">
                <template slot-scope="scope">
                    <el-button type="text" v-if="[0,2,3,4].indexOf(scope.row.status) !== -1"
                               @click="handleRemove(scope.row)">删除
                    </el-button>
                    <el-button type="text" v-if="3 === scope.row.status"
                               @click="upload(scope.row)">再次尝试上传
                    </el-button>
                </template>
            </el-table-column>
        </el-table>
    </div>
</template>

<script>
    import queue from 'async/queue';

    const headers = {'Content-Type': 'application/x-www-form-urlencoded'};
    let q;
    export default {
        name: "upload_file_table",
        props: {
            placeholder: {},
            url: {required: true,},
            defaultFiles: {default: [],}
        },
        data() {
            return {
                uploading: false,
                files: [],
            }
        },
        mounted() {
            q = queue((data, cb) => {
                //已经从队列中移除了任务
                if (this.files.indexOf(data) === -1)
                    return cb();
                this.upload(data, cb);
            }, 1);
        },
        watch: {
            defaultFiles(val) {
                _.each(val, file => {
                    this.files.push({file, status: 4});
                });
            }
        },
        methods: {
            selectedFile() {
                _.each(this.$refs.fileInput.files, file => {
                    //检查文件
                    if (!this.checkFile(file))
                        return this.$message.error(file.name + ' 大小超过 10MB');
                    //检查是否重复上传
                    if (_.find(this.files, {file: {name: file.name}}))
                        return this.$message.error(file.name + ' 已经在队列中了');
                    let data = {file, status: 0};
                    this.files.push(data);
                    q.push(data);
                });
            },
            upload(data, cb) {
                const form = new FormData();
                form.append('file', data.file);
                data.status = 1;
                this.$http({method: 'post', url: this.url, headers, data: form}).then(res => {
                    data.status = 2;
                    data.file.file = res.data.file;
                }).catch(err => {
                    data.status = 3;
                    data.error = err.response.data;
                    this.$message.error(err.response.data);
                }).finally(() => {
                    if (cb)
                        cb();
                });
            },
            checkFile(file) {
                const fileSizeLimit = file.size / 1024 / 1024 < 10;
                return fileSizeLimit;
            },
            handleRemove(data) {
                let file = data.file;
                if (file.file)
                    this.$confirm(`确定移除 ${ file.name }？`, {type: 'warning'}).then(() => {
                        this.$http.delete('/file/' + file.file)
                            .then(res => {
                                this.files.splice(this.files.indexOf(data), 1);
                            })
                            .catch(err => {
                                this.$message.error(err.response.data);
                            });
                    });
                else
                    this.files.splice(this.files.indexOf(data), 1);
            },
            clickFile(file) {
                if ([2, 4].indexOf(file.status) === -1)
                    return;
                this.$emit('click', file.file);
            },
        },
    }
</script>

<style scoped>
</style>